「つらみが解決!Rainを使ってCloudFormationをもっと便利に」というテーマで話しました #devio2021

「つらみが解決!Rainを使ってCloudFormationをもっと便利に」というテーマで話しました #devio2021

Clock Icon2021.10.12

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

セッションの概要

DevelopersIO 2021 Decadeという弊社オンラインイベントにて、「つらみが解決!Rainを使ってCloudFormationをもっと便利に」というテーマで話しました。

動画

スライド

ソースコード

「個人的Rainのベストプラクティス」のテンプレートやGitHub Actionsのworkflowsのソースコードを共有します。やってみたなどでご利用ください。

system.yml(ネストされたテンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

  ### Vpc Parameters 

  vpcCidr:
    Type: String

  ### Acm And Route53 Parameters

  domainName:
    Type: String

  hostedZoneId:
    Type: String

  ### Ec2 Parameters

  instanceType:
    Type: String

  ### Rds Parameters

  instanceClass:
    Type: String

  masterPassword:
    Type: String
    NoEcho: true

Resources:
  ### VPC

  Vpc:
    Type: AWS::CloudFormation::Stack
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
        vpcCidr: !Ref vpcCidr
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-vpc-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: ./template/vpc.yml

  ### Iam

  Iam:
    Type: AWS::CloudFormation::Stack
    DependsOn: Vpc
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-iam-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/iam.yml

  ### Acm

  Acm:
    Type: AWS::CloudFormation::Stack
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
        domainName: !Ref domainName
        hostedZoneId: !Ref hostedZoneId
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-acm-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/acm.yml

  ### Security Group

  SecurityGroup:
    Type: AWS::CloudFormation::Stack
    DependsOn: Vpc
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-securitygroup-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/securitygroup.yml

  ### Rds

  Rds:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - SecurityGroup
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
        instanceClass: !Ref instanceClass
        masterPassword: !Ref masterPassword
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-rds-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/rds.yml

  ### Ec2

  Ec2:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - SecurityGroup
      - Iam
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
        instanceType: !Ref instanceType
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-ec2-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/ec2.yml

  ### ALb

  Alb:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - SecurityGroup
      - Acm
      - Ec2
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        billingTag: !Ref billingTag
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-alb-stacks
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/alb.yml

  ### Route 53

  route53:
    Type: AWS::CloudFormation::Stack
    DependsOn:
      - Alb
    Properties:
      Parameters:
        env: !Ref env
        sysName: !Ref sysName
        domainName: !Ref domainName
        hostedZoneId: !Ref hostedZoneId
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-route53-stack
        - Key: BillingGroup
          Value: !Ref billingTag
      TemplateURL: !Rain::S3Http ./template/route53.yml

vpc.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

  ### Vpc Parameters 

  vpcCidr:
    Type: String

Resources:
  ### VPC

  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref vpcCidr
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-vpc
        - Key: BillingGroup
          Value: !Ref billingTag

  ### Internet Gateway

  MyInternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-igw
        - Key: BillingGroup
          Value: !Ref billingTag

  MyVPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref MyInternetGateway
      VpcId: !Ref MyVPC

  ### Public Subnet 

  MyPublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 0
        - !GetAZs
          Ref: AWS::Region
      CidrBlock: !Select [0, !Cidr [!GetAtt MyVPC.CidrBlock, 2, 8]]
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-public-subnet-1
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  MyPublicSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 1
        - !GetAZs
          Ref: AWS::Region
      CidrBlock: !Select [1, !Cidr [!GetAtt MyVPC.CidrBlock, 2, 8]]
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-public-subnet-2
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  ### Public Route Table

  MyPublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-public-rtb
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  MyPublicRoute:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref MyInternetGateway
      RouteTableId: !Ref MyPublicRouteTable

  MyPublicSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPublicRouteTable
      SubnetId: !Ref MyPublicSubnet1

  MyPublicSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPublicRouteTable
      SubnetId: !Ref MyPublicSubnet2

  ### Private Subnet 

  MyPrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 0
        - !GetAZs
          Ref: AWS::Region
      CidrBlock: !Select [10, !Cidr [!GetAtt MyVPC.CidrBlock, 12, 8]]
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-private-subnet-1
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  MyPrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select
        - 1
        - !GetAZs
          Ref: AWS::Region
      CidrBlock: !Select [11, !Cidr [!GetAtt MyVPC.CidrBlock, 12, 8]]
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-private-subnet-2
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  ### Private Route Table

  MyPrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-private-rtb
        - Key: BillingGroup
          Value: !Ref billingTag
      VpcId: !Ref MyVPC

  MyPrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref MyInternetGateway
      RouteTableId: !Ref MyPrivateRouteTable

  MyPrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPrivateRouteTable
      SubnetId: !Ref MyPrivateSubnet1

  MyPrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref MyPrivateRouteTable
      SubnetId: !Ref MyPrivateSubnet2
      ### Outputs

Outputs:
  MyVPC:
    Value: !Ref MyVPC
    Export:
      Name: !Sub ${env}-${sysName}-MyVPC

  MyPublicSubnet1:
    Value: !Ref MyPublicSubnet1
    Export:
      Name: !Sub ${env}-${sysName}-MyPublicSubnet1

  MyPublicSubnet2:
    Value: !Ref MyPublicSubnet2
    Export:
      Name: !Sub ${env}-${sysName}-MyPublicSubnet2

  MyPrivateSubnet1:
    Value: !Ref MyPrivateSubnet1
    Export:
      Name: !Sub ${env}-${sysName}-MyPrivateSubnet1

  MyPrivateSubnet2:
    Value: !Ref MyPrivateSubnet2
    Export:
      Name: !Sub ${env}-${sysName}-MyPrivateSubnet2

securitygroup.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

Resources:
  ### Security Group Alb

  AlbSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Application load barancer.
      GroupName: !Sub ${env}-${sysName}-alb-sg
      VpcId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-alb-sg
        - Key: BillingGroup
          Value: !Ref billingTag

  ### Security Group ec2

  ec2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ec2 Instances.
      GroupName: !Sub ${env}-${sysName}-ec2-sg
      VpcId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref AlbSG
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-ec2-sg
        - Key: BillingGroup
          Value: !Ref billingTag

  ### Security Group Rds

  RdsSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Rds Instances.
      GroupName: !Sub ${env}-${sysName}-rds-sg
      VpcId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !Ref ec2SG
      SecurityGroupEgress:
        - IpProtocol: "-1"
          FromPort: 0
          ToPort: 0
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-rds-sg
        - Key: BillingGroup
          Value: !Ref billingTag
          ### Outputs

Outputs:
  AlbSG:
    Value: !Ref AlbSG
    Export:
      Name: !Sub ${env}-${sysName}-alb-sg

  ec2SG:
    Value: !Ref ec2SG
    Export:
      Name: !Sub ${env}-${sysName}-ec2-sg

  RdsSG:
    Value: !Ref RdsSG
    Export:
      Name: !Sub ${env}-${sysName}-rds-sg

iam.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

Resources:
  ### ec2 Profilee

  ec2Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess

  ec2Profile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref ec2Role

Outputs:
  ec2Profile:
    Value: !Ref ec2Profile
    Export:
      Name: !Sub ${env}-${sysName}-ec2Profile

acm.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

  ### Acm And Route53 Parameters

  domainName:
    Type: String

  hostedZoneId:
    Type: String

Resources:
  ### Alb Acm

  AlbAcm:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Ref domainName
      DomainValidationOptions:
        - DomainName: !Ref domainName
          HostedZoneId: !Ref hostedZoneId
      ValidationMethod: DNS
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-albacm
        - Key: BillingGroup
          Value: !Ref billingTag
          ### Outputs

Outputs:
  AlbAcm:
    Value: !Ref AlbAcm
    Export:
      Name: !Sub ${env}-${sysName}-albacm

ec2.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

  ### Ec2 Parameters

  ec2Ami:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

  instanceType:
    Type: String

Resources:
  ### ec2 Instance

  Instance1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ec2Ami
      InstanceType: !Ref instanceType
      CreditSpecification:
        CPUCredits: standard
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeType: gp3
            Iops: 3000
            VolumeSize: 8
            Encrypted: true
      SecurityGroupIds:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-ec2-sg
      SubnetId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyPrivateSubnet1
      IamInstanceProfile: !ImportValue
        Fn::Sub: ${env}-${sysName}-ec2Profile
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-instance1
        - Key: BillingGroup
          Value: !Ref billingTag

  Instance2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ec2Ami
      InstanceType: !Ref instanceType
      CreditSpecification:
        CPUCredits: standard
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            VolumeType: gp3
            Iops: 3000
            VolumeSize: 8
            Encrypted: true
      SecurityGroupIds:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-ec2-sg
      SubnetId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyPrivateSubnet2
      IamInstanceProfile: !ImportValue
        Fn::Sub: ${env}-${sysName}-ec2Profile
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-instance2
        - Key: BillingGroup
          Value: !Ref billingTag

Outputs:
  Instance1:
    Value: !Ref Instance1
    Export:
      Name: !Sub ${env}-${sysName}-instance1

  Instance2:
    Value: !Ref Instance2
    Export:
      Name: !Sub ${env}-${sysName}-instance2

rds.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

  ### Rds Parameters

  instanceClass:
    Type: String

  masterPassword:
    Type: String
    NoEcho: true

Resources:
  ### Rds Subnet Group

  SubnetGroupRds:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: !Sub ${env}-${sysName}-rds-SubnetGroup
      DBSubnetGroupName: !Sub ${env}-${sysName}-rds-subnetgroup
      SubnetIds:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-MyPrivateSubnet1
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-MyPrivateSubnet2
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-rds-SubnetGroup
        - Key: BillingGroup
          Value: !Ref billingTag

  ### Rds Parameter Group

  ParameterGroupAurora:
    Type: AWS::RDS::DBParameterGroup
    Properties:
      Description: !Sub ${env}-${sysName}-parametergroup
      Family: aurora-mysql5.7

  ## Rds Cluster Parameter Group

  clusterParameterGroupAurora:
    Type: AWS::RDS::DBClusterParameterGroup
    Properties:
      Description: !Sub ${env}-${sysName}-cluster-parametergroup
      Family: aurora-mysql5.7
      Parameters:
        character_set_client: utf8
        character_set_connection: utf8
        character_set_database: utf8
        character_set_results: utf8
        character_set_server: utf8
        general_log: 1
        server_audit_events: CONNECT,QUERY,QUERY_DCL,QUERY_DDL,QUERY_DML,TABLE
        server_audit_logging: 1
        slow_query_log: 1
        time_zone: Asia/Tokyo

  ### Rds Aurora Cluster

  clusterAurora:
    Type: AWS::RDS::DBCluster
    Properties:
      MasterUsername: root
      MasterUserPassword: !Ref masterPassword
      DBClusterIdentifier: !Sub ${env}-${sysName}-cluster
      Engine: aurora-mysql
      EngineVersion: 5.7.mysql_aurora.2.10.0
      DBClusterParameterGroupName: !Ref clusterParameterGroupAurora
      DBSubnetGroupName: !Ref SubnetGroupRds
      DeletionProtection: false
      Port: 3306
      PreferredBackupWindow: 17:00-18:00
      BackupRetentionPeriod: 7
      PreferredMaintenanceWindow: tue:18:00-tue:19:00
      EnableCloudwatchLogsExports:
        - audit
        - error
        - general
        - slowquery
      StorageEncrypted: true
      VpcSecurityGroupIds:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-rds-sg
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-cluster
        - Key: BillingGroup
          Value: !Ref billingTag

  # Rds Aurora Instance1

  DbInstance1:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceIdentifier: !Sub ${env}-${sysName}-db1
      DBClusterIdentifier: !Ref clusterAurora
      DBInstanceClass: !Ref instanceClass
      Engine: aurora-mysql
      DBParameterGroupName: !Ref ParameterGroupAurora
      AutoMinorVersionUpgrade: false
      PubliclyAccessible: false
      MonitoringInterval: 0
      EnablePerformanceInsights: false
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-db1
        - Key: BillingGroup
          Value: !Ref billingTag

  # Rds Aurora Instance2

  DbInstance2:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceIdentifier: !Sub ${env}-${sysName}-db2
      DBClusterIdentifier: !Ref clusterAurora
      DBInstanceClass: !Ref instanceClass
      Engine: aurora-mysql
      DBParameterGroupName: !Ref ParameterGroupAurora
      AutoMinorVersionUpgrade: false
      PubliclyAccessible: false
      MonitoringInterval: 0
      EnablePerformanceInsights: false
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-db2
        - Key: BillingGroup
          Value: !Ref billingTag

alb.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  billingTag:
    Type: String

Resources:
  ### Alb

  Alb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      IpAddressType: ipv4
      Name: !Sub ${env}-${sysName}-alb
      Scheme: internet-facing
      SecurityGroups:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-alb-sg
      Subnets:
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-MyPublicSubnet1
        - !ImportValue
          Fn::Sub: ${env}-${sysName}-MyPublicSubnet2
      Type: application
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-api
        - Key: BillingGroup
          Value: !Ref billingTag

  AlbListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Certificates:
        - CertificateArn: !ImportValue
            Fn::Sub: ${env}-${sysName}-albacm
      DefaultActions:
        - FixedResponseConfig:
            ContentType: text/plain
            MessageBody: Unauthorized Access
            StatusCode: "403"
          Type: fixed-response
      LoadBalancerArn: !Ref Alb
      Port: 443
      Protocol: HTTPS
      SslPolicy: ELBSecurityPolicy-2016-08

  AlbListnerRule1:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - TargetGroupArn: !Ref TargetGroup
          Type: forward
      Conditions:
        - Field: path-pattern
          PathPatternConfig:
            Values:
              - '*'
      ListenerArn: !Ref AlbListener
      Priority: 1

  ### Target Group for ec2 Instance

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub ${env}-${sysName}-ec2
      Port: 80
      Protocol: HTTP
      TargetType: instance
      Targets:
        - Id: !ImportValue
            Fn::Sub: ${env}-${sysName}-instance1
        - Id: !ImportValue
            Fn::Sub: ${env}-${sysName}-instance2
      VpcId: !ImportValue
        Fn::Sub: ${env}-${sysName}-MyVPC
      Tags:
        - Key: Name
          Value: !Sub ${env}-${sysName}-tg
        - Key: BillingGroup
          Value: !Ref billingTag
          ### Outputs

Outputs:
  AlbDomainName:
    Value: !Join
      - ""
      - - dualstack.
        - !GetAtt Alb.DNSName
    Export:
      Name: !Sub ${env}-${sysName}-alb-domain

route53.yml(子テンプレート)
AWSTemplateFormatVersion: "2010-09-09"

Description: Template generated by rain

Parameters:
  ### Common Parameters

  env:
    Type: String

  sysName:
    Type: String

  ### Acm And Route53 Parameters

  domainName:
    Type: String

  hostedZoneId:
    Type: String

Resources:
  ### Alb DNS Record

  AlbRecordSet:
    Type: AWS::Route53::RecordSet
    Properties:
      Name: !Ref domainName
      Type: A
      AliasTarget:
        HostedZoneId: Z14GRHDCWA56QT
        DNSName: !ImportValue
          Fn::Sub: ${env}-${sysName}-alb-domain
        EvaluateTargetHealth: false
      HostedZoneId: !Ref hostedZoneId

dev-deploy.yml(GitHub Actions)
name: cfn deploy

### devブランチのpushがトリガー

on:
  push:
    branches: 
      - dev

  workflow_dispatch:

### envは環境に応じて修正

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions: 
      id-token: write
      contents: read
    env:
      ENV: dev
      SYSNAME: example
      BILLINGTAG: example
      CIDR: 10.255.0.0/16
      DOMAIN_NAME: dev.example.com
      HOSTED_ZONE_ID: Z10116024XXXXXXXXXXX
      INSTANCE_TYPE: t3.micro
      INSTANCE_CLASS: db.t3.small
      MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }}

    steps:
      - name: setup
        run: |
          brew install rain
          echo "rain -v"
          rain -v

      - name: there's still a race condition for now
        run: sleep 5

### AWS_ROLE_ARN、AWS_DEFAULT_REGION変数は環境に応じて修正

      - name: Configure AWS
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole
          export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds
          export AWS_DEFAULT_REGION=ap-northeast-1

          echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV
          echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV

          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE

      - uses: actions/checkout@v2
        with:
          ref: dev

      - name: Check the Format of the CloudFormation template.
        run: |
          echo Returns an error if not formatted.
          rain fmt -v ./template/*yml

      - name: Template deploy.
        run: |
          rain deploy -y ./system.yml $ENV-stack --params \
          env=$ENV,\
          sysName=$SYSNAME,\
          billingTag=$BILLINGTAG,\
          vpcCidr=$CIDR,\
          domainName=$DOMAIN_NAME,\
          hostedZoneId=$HOSTED_ZONE_ID,\
          instanceType=$INSTANCE_TYPE,\
          instanceClass=$INSTANCE_CLASS,\
          masterPassword=$MASTERPASSWORD

stg-deploy.yml(GitHub Actions)
name: cfn deploy

### stgブランチのpushがトリガー

on:
  push:
    branches: 
      - stg

  workflow_dispatch:

### envは環境に応じて修正

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions: 
      id-token: write
      contents: read
    env:
      ENV: stg
      SYSNAME: example
      BILLINGTAG: example
      CIDR: 10.254.0.0/16
      DOMAIN_NAME: stg.example.com
      HOSTED_ZONE_ID: Z10116024XXXXXXXXXXX
      INSTANCE_TYPE: t3.micro
      INSTANCE_CLASS: db.t3.small
      MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }}

    steps:
      - name: setup
        run: |
          brew install rain
          echo "rain -v"
          rain -v

      - name: there's still a race condition for now
        run: sleep 5

### AWS_ROLE_ARN、AWS_DEFAULT_REGION変数は環境に応じて修正

      - name: Configure AWS
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole
          export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds
          export AWS_DEFAULT_REGION=ap-northeast-1

          echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV
          echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV

          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE

      - uses: actions/checkout@v2
        with:
          ref: stg

      - name: Check the Format of the CloudFormation template.
        run: |
          echo Returns an error if not formatted.
          rain fmt -v ./template/*yml

      - name: Template deploy.
        run: |
          rain deploy -y ./system.yml $ENV-stack --params \
          env=$ENV,\
          sysName=$SYSNAME,\
          billingTag=$BILLINGTAG,\
          vpcCidr=$CIDR,\
          domainName=$DOMAIN_NAME,\
          hostedZoneId=$HOSTED_ZONE_ID,\
          instanceType=$INSTANCE_TYPE,\
          instanceClass=$INSTANCE_CLASS,\
          masterPassword=$MASTERPASSWORD

prd-deploy.yml(GitHub Actions)
name: cfn deploy

### mainブランチのpushがトリガー

on:
  push:
    branches: 
      - main

  workflow_dispatch:

### envは環境に応じて修正

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions: 
      id-token: write
      contents: read
    env:
      ENV: prd
      SYSNAME: example
      BILLINGTAG: example
      CIDR: 10.0.0.0/16
      DOMAIN_NAME: example.com
      HOSTED_ZONE_ID: Z10116024ZZZZZZZZZZ
      INSTANCE_TYPE: m5.large
      INSTANCE_CLASS: db.m5.large
      MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }}

    steps:
      - name: setup
        run: |
          brew install rain
          echo "rain -v"
          rain -v

      - name: there's still a race condition for now
        run: sleep 5

### AWS_ROLE_ARN、AWS_DEFAULT_REGION変数は環境に応じて修正

      - name: Configure AWS
        run: |
          export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole
          export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds
          export AWS_DEFAULT_REGION=ap-northeast-1

          echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV
          echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV
          echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV

          curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE

      - uses: actions/checkout@v2
        with:
          ref: main

      - name: Check the Format of the CloudFormation template.
        run: |
          echo Returns an error if not formatted.
          rain fmt -v ./template/*yml

      - name: Template deploy.
        run: |
          rain deploy -y ./system.yml $ENV-stack --params \
          env=$ENV,\
          sysName=$SYSNAME,\
          billingTag=$BILLINGTAG,\
          vpcCidr=$CIDR,\
          domainName=$DOMAIN_NAME,\
          hostedZoneId=$HOSTED_ZONE_ID,\
          instanceType=$INSTANCE_TYPE,\
          instanceClass=$INSTANCE_CLASS,\
          masterPassword=$MASTERPASSWORD

リンク

rain
GitHub ActionsでAWSの永続的なクレデンシャルを渡すことなくIAM Roleが利用できるようになったようです
※ 当初公開されていたGitHub Actionsが引き受けるIAMロールを作成するCloudFormationテンプレートのOIDCプロバイダURLが変更されました。
変更前:https://vstoken.actions.githubusercontent.com
変更後:https://token.actions.githubusercontent.com
AWS federation comes to GitHub Actions

おわりに

DevelopersIO 2021 Decade では、他にも多数の ビデオセッション が順次公開されています。 また、10/5 〜 10/14 の期間中に ライブセッション も開催されますので、そちらもチェックしていただけると幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.